/**
 * 
 */
package org.vsg.security.model.presentation.spring;

import java.util.Collection;
import java.util.List;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.vsg.common.pagination.Pagination;
import org.vsg.common.pagination.apps.HttpApplicationContext;
import org.vsg.common.pagination.apps.HttpPaginationApplicationContextFactory;
import org.vsg.common.pagination.apps.PaginationApplicationContext;
import org.vsg.common.pagination.apps.RecordLimitCarrierApplicationContext;
import org.vsg.common.pagination.carrier.HttpSingleSortRecordLimitCarrier;
import org.vsg.common.pagination.carrier.RecordLimitCarrier;
import org.vsg.common.web.json.ListResult;
import org.vsg.common.web.json.LoadRecordResult;
import org.vsg.common.web.json.SubmitResult;
import org.vsg.common.web.json.processor.JsTimestampJsonValueProcessor;
import org.vsg.security.model.domain.ResourceAssociation;
import org.vsg.security.model.domain.SysMenuResource;
import org.vsg.security.model.domain.SysOperation;
import org.vsg.security.model.domain.SysResource;
import org.vsg.security.model.domain.SysRole;
import org.vsg.security.model.domain.UrlResource;
import org.vsg.security.model.service.SysMenuResourceService;
import org.vsg.security.model.service.SysRoleService;
import org.vsg.security.model.service.UrlResourceService;
import org.vsg.security.model.vo.json.AssociationMenuTreeNodeColumn;
import org.vsg.security.model.vo.json.BindingUrlResourceVO;
import org.vsg.security.model.vo.json.MenuFormVO;
import org.vsg.security.model.vo.json.MenuListVO;
import org.vsg.security.model.vo.json.MenuResourceNodeWithChildrenVO;
import org.vsg.security.model.vo.json.MenuTreeNodeColumn;



/**
 * @author Bill vison
 *
 */
@Controller
public class MenuController {

	private final static Logger logger = LoggerFactory.getLogger(MenuController.class);	
	
	@Autowired	
	private SysMenuResourceService sysMenuResourceService;

	@Autowired	
	private UrlResourceService urlResourceService;	

	@Autowired
	private SysRoleService sysRoleService;	
	
	@RequestMapping("/treeMenu.do")
	public String treeMenu(HttpServletRequest request , HttpServletResponse res) throws Exception {
		Collection<MenuResourceNodeWithChildrenVO> rootList = sysMenuResourceService.findAllMenuResourceByRoot();
		

		// --- generate tree node ---
		List<MenuTreeNodeColumn> allTreeNode = generateExtTreeNode(rootList);		

		JsonConfig jcfg = new JsonConfig();
		jcfg.registerJsonValueProcessor(java.sql.Timestamp.class, new JsTimestampJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(allTreeNode ,jcfg ); 
		
		request.setAttribute("json", jsonObject);
		
		logger.info( jsonObject.toString() );
		
		return "json";
	}
	
	@RequestMapping("/addMenu.do")
	public String addMenu(HttpServletRequest req , HttpServletResponse res , SysMenuResource resource) throws Exception {
		
		// insert entity
		sysMenuResourceService.addSysMenuResource( resource );

		
		// --- json result object ---
		SubmitResult submitResult = new SubmitResult();
		submitResult.setSuccess(true);
		submitResult.setMsg("新增成功!");

		
		JSONObject jsonObject = JSONObject.fromObject(submitResult ); 
		
		req.setAttribute("json", jsonObject);
		
		return "result";
	}
	
	
	@RequestMapping("/updateMenu.do")
	public String updateMenu(HttpServletRequest req , HttpServletResponse res , SysMenuResource resource) throws Exception {
		
		sysMenuResourceService.updateSimpleSysMenuResource( resource );

		// --- json result object ---
		SubmitResult submitResult = new SubmitResult();
		submitResult.setSuccess(true);
		submitResult.setMsg("修改成功!");		
		JSONObject jsonObject = JSONObject.fromObject(submitResult ); 
		
		req.setAttribute("json", jsonObject);			
				
		
		return "result";
	}
	
	@RequestMapping("/loadMenu.do")
	public String loadMenu(HttpServletRequest req , HttpServletResponse res , long menuId) throws Exception {
		
		SysMenuResource resource = sysMenuResourceService.loadSysMenuResource( menuId );
		
		MenuFormVO vo = new MenuFormVO(resource);
		
		long parentId = resource.getParentId();
		if (parentId > 0) {
			SysMenuResource parentResource = sysMenuResourceService.loadSysMenuResource(parentId);
			vo.setParentMenu( parentResource.getName() );
		}
	
		// --- json result object ---
		LoadRecordResult recordResult = new LoadRecordResult();
		recordResult.setSuccess(true);
		recordResult.setData( vo );

		JsonConfig jcfg = new JsonConfig();
		jcfg.registerJsonValueProcessor(java.sql.Timestamp.class, new JsTimestampJsonValueProcessor());

		JSONObject jsonObject = JSONObject.fromObject( recordResult  , jcfg); 
		
		logger.debug( jsonObject.toString() );
	
		req.setAttribute("json", jsonObject);
		
		return "result";
	}

	@RequestMapping("/removeMenus.do")	
	public String removeMenus(HttpServletRequest req  , long[] menuId) throws Exception {
		
		sysMenuResourceService.removeMenus(menuId);

		
		// --- json result object ---
		SubmitResult submitResult = new SubmitResult();
		submitResult.setSuccess(true);
		submitResult.setMsg( "移除菜单数据成功" );

		JSONObject jsonObject = JSONObject.fromObject(submitResult ); 
		
		req.setAttribute("json", jsonObject);
		
		// --- use log show
		logger.info(jsonObject.toString());			
		return "result";
	}
	
	@RequestMapping("/pageAvailableMenu.do")
	public String pageAvailableMenu(HttpServletRequest req , HttpServletResponse res) throws Exception {
		// generate pagination application and set the request
		PaginationApplicationContext pageAppsContext = HttpPaginationApplicationContextFactory.getPaginationContext(req);
		// set parameter passed in pagination url
		RecordLimitCarrierApplicationContext recordLimitAppsContenxt = (RecordLimitCarrierApplicationContext)pageAppsContext;
		
		HttpApplicationContext httpContext = (HttpApplicationContext)pageAppsContext;
		
		httpContext.addParameterName("name");
		httpContext.addParameterName("resourceId");		
		
		// set the data to attribute
		RecordLimitCarrier limitCarrier = recordLimitAppsContenxt.generateRecordLimitCarrier( HttpSingleSortRecordLimitCarrier.class );
		
		Pagination page = sysMenuResourceService.pageSysMenuResource(limitCarrier);
		
		Collection<SysMenuResource> menuList = page.getPaginationList();
		
		Collection<MenuListVO> tmpRoleVoList = new Vector<MenuListVO>();
		for (SysMenuResource menu : menuList) {
			tmpRoleVoList.add(new MenuListVO(menu));
		}
		
		// --- parse the json ---
		ListResult lr = new ListResult();
		lr.setResults( page.getTotalRecord() );
		lr.setRows( tmpRoleVoList );
		
		JsonConfig jcfg = new JsonConfig();
		jcfg.registerJsonValueProcessor(java.sql.Timestamp.class, new JsTimestampJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(lr ,jcfg ); 
		
		// --- set attribute ---
		req.setAttribute("json", jsonObject);		
		
		return "json";
	}	

	@RequestMapping("/loadBindingUrlResource.do")	
	public String loadBindingUrlResource(HttpServletRequest req , HttpServletResponse res , Long menuId) throws Exception {
		
		SysMenuResource resource = sysMenuResourceService.loadSysMenuResource(menuId );

		SysResource sysResource = resource.getAssociationResource();
		UrlResource urlResource = urlResourceService.loadUrlResource(sysResource.getId() );
		
		
		BindingUrlResourceVO bindUrlResource = new BindingUrlResourceVO();
		bindUrlResource.setOrgId( urlResource.getId() );
		bindUrlResource.setOrgModule( urlResource.getContext() );
		bindUrlResource.setOrgURL( urlResource.getUrl() );

		// --- json result object ---
		LoadRecordResult recordResult = new LoadRecordResult();
		recordResult.setSuccess(true);
		recordResult.setData( bindUrlResource );

		JsonConfig jcfg = new JsonConfig();
		jcfg.registerJsonValueProcessor(java.sql.Timestamp.class, new JsTimestampJsonValueProcessor());

		JSONObject jsonObject = JSONObject.fromObject( recordResult  , jcfg); 
	
		req.setAttribute("json", jsonObject);		

		// --- use log show
		logger.info(jsonObject.toString());	
		
		return "json";
	}

	@RequestMapping("/updateBindingUrlResource.do")	
	public String updateBindingUrlResource(HttpServletRequest req , HttpServletResponse res  ,  Long menuId , Long urlResourceId) throws Exception {
		
	
		SysMenuResource menuResource = new SysMenuResource();
		menuResource.setId( menuId );
		
		UrlResource urlResource = new UrlResource();
		urlResource.setId( urlResourceId );
		
		urlResourceService.bindingMenuUrlResource(urlResource, menuResource);

		// --- json result object ---
		SubmitResult submitResult = new SubmitResult();
		submitResult.setSuccess(true);
		submitResult.setMsg( "绑定菜单成功" );		
		JSONObject jsonObject = JSONObject.fromObject(submitResult ); 
		
		req.setAttribute("json", jsonObject);			
		
		return "result";
	}
	
	@RequestMapping("/treeOneRoleAssociationMenu.do")		
	public String  treeOneRoleAssociationMenu(HttpServletRequest req , HttpServletResponse res , Integer roleId) throws Exception {
	
		SysRole sysRole = this.sysRoleService.loadSysRole(roleId);
			
		Collection<MenuResourceNodeWithChildrenVO> rootList = this.sysMenuResourceService.findAllMenuResourceByRoot();

		// --- generate tree node ---
		List<AssociationMenuTreeNodeColumn> allTreeNode = generateAuthorizationTreeNode(rootList , sysRole);		

		JsonConfig jcfg = new JsonConfig();
		JSONArray jsonObject = JSONArray.fromObject(allTreeNode ); 
		
		req.setAttribute("json", jsonObject);		
		
		return "json";
	}

	
	@RequestMapping("/updateOneRoleMenuAssociation.do")	
	public String updateOneRoleMenuAssociation(HttpServletRequest req , HttpServletResponse res , Long menuId , Integer roleId ,  String authAssign) throws Exception {

		
		SysMenuResource menuResource = new SysMenuResource();
		menuResource.setId( menuId );
		
		SysRole role = new SysRole();
		role.setId( roleId );
		
		SysOperation operation = new SysOperation();
		operation.setOperation( authAssign );
		
		
		sysMenuResourceService.bindingMenuRoleAssociation(menuResource, operation, role);


		
		// --- json result object ---
		SubmitResult submitResult = new SubmitResult();
		submitResult.setSuccess(true);
		submitResult.setMsg( "权限设定成功!" );
		
		JSONObject jsonObject = JSONObject.fromObject(submitResult ); 
		
		req.setAttribute("json", jsonObject);
		
		// --- use log show
		logger.info(jsonObject.toString());		
		
		return "result";
	}
	
	
	private List<MenuTreeNodeColumn> generateExtTreeNode(Collection<MenuResourceNodeWithChildrenVO> rootList) throws Exception {
		

		List<MenuTreeNodeColumn> allTree = new Vector<MenuTreeNodeColumn>();

		// --- run node child ren ---
		MenuTreeNodeColumn node = null;
		for (MenuResourceNodeWithChildrenVO sub : rootList) {
			node = new MenuTreeNodeColumn();
			
			node.setId( sub.getMenuResource().getId() );
			node.setLeaf( sub.isIfLeaf() );
			node.setText( sub.getMenuResource().getName() );
			node.setName( sub.getMenuResource().getName() );
			node.setPolicy( sub.getMenuResource().getFlagStrategy() );
			node.setDisabled( sub.getMenuResource().getFlagDisabled() );
			node.setUiProvider("col");

			if (!sub.isIfLeaf()) {
				List<MenuTreeNodeColumn> subChildNode = generateExtTreeNode(sub.getChildren());
				node.setIconCls("tree-folder");
				node.setChildren( subChildNode );
			} else {
				node.setIconCls("leaf");
			
			}
			
			allTree.add( node );			
		}

		
		return allTree;
	}	

	private List<AssociationMenuTreeNodeColumn> generateAuthorizationTreeNode(Collection<MenuResourceNodeWithChildrenVO> rootList, SysRole role) throws Exception {
		
		List<AssociationMenuTreeNodeColumn> allTree = new Vector<AssociationMenuTreeNodeColumn>();

		// --- run node children ---
		AssociationMenuTreeNodeColumn node = null;
		for (MenuResourceNodeWithChildrenVO sub : rootList) {
			node = new AssociationMenuTreeNodeColumn();
			
			node.setId( sub.getMenuResource().getId() );
			node.setLeaf( sub.isIfLeaf() );
			node.setText( sub.getMenuResource().getName() );
			node.setName( sub.getMenuResource().getName() );
			
			// ---- check the permission defined -----
			Collection<ResourceAssociation> allPermission = sub.getMenuResource().getPermissions();
			for (ResourceAssociation permission : allPermission) {
				if (permission.getRole() == role) {
					SysOperation operation = permission.getOperation();
					node.setAuthorization(  operation.getName() );
					break;
				}
			}
			
			// --- set the not defined ---
			if (node.getAuthorization() == null) {
				node.setAuthorization("没有设定");
			}
			
			

			node.setUiProvider("col");

			if (!sub.isIfLeaf()) {
				List<AssociationMenuTreeNodeColumn> subChildNode = generateAuthorizationTreeNode(sub.getChildren() , role);
				node.setIconCls("tree-folder");
				node.setChildren( subChildNode );
			} else {
				node.setIconCls("leaf");
			
			}
			
			allTree.add( node );			
		}

		
		return allTree;
	}	
	
	
}
